
/*
* @version: 1.0
* @Author: zhanggq
* @Date: 2023-01-28 10:01:00
* @LastEditTime: 2023-01-31 16:39:30
* @Description: iec104通信管理
*/

#ifndef   __IEC104_COMM_HANDLER__
#define   __IEC104_COMM_HANDLER__

#include "../../include/lib60870/cs104_slave.h"
#include "../../include/lib60870/cs104_connection.h"

#include "DCData.h"
#include "CConfigManager.h"
#include "DataCenterManager.h"

#include "Iec104ServiceManager.h"

#include <list>
using namespace  std;



class CIec104CommHandler
{
public:
    CIec104CommHandler();
    ~CIec104CommHandler();

    CIec104CommHandler*  getInstance();
    void    init(std::shared_ptr<CConfigManager> cm,std::shared_ptr<DataCenterManager> dcm,
                std::shared_ptr<CMosquittoManager> mm, std::shared_ptr<TaskManager> tm,bool reverse=false);

    int  client_init();
    void client_stop();
    int  reverse_client_init();
    int  normal_client_init();

    //单点/双点或测量值ASDU创建----ca 公共地址,ti类型标识,cot传送原因
    void  create_send_singlePoint_Asdu(int ca, int ti, int cot, std::list<ST_IEC104_PTVAL> lstObjs, IMasterConnection connection,bool bInterr=true);
    void  create_send_doublePoint_Asdu(int ca, int ti, int cot, std::list<ST_IEC104_PTVAL> lstObjs, IMasterConnection connection, bool bInterr = true);
    void  create_send_MeasuredPoint_Asdu(int ca, int ti, int cot, std::list<ST_IEC104_MEAR_VAL> lstMearObjs, IMasterConnection connection, bool bInterr = true);
    void  create_send_CounterInterr_Asdu(int ca, int ti, int cot, std::list<ST_IEC104_INTERTOTAL_VAL> lstMearObjs, IMasterConnection connection, bool bInterr = true);

    //遥信换位或遥测超过死区主动上报
    int  LocalSpontReport(std::string& dev, std::list<ST_CHANGE_REPORT_DATAPT>& lstChangeReportPts);

    //时钟同步处理
    static bool clockSyncHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu, CP56Time2a newTime);
    //连接请求处理
    static bool connectionRequestHandler(void* parameter, const char* ipAddress);
    //连接事件处理
    static void connectionEventHandler(void* parameter, IMasterConnection con, CS104_PeerConnectionEvent event);
    //主站召唤响应
    static bool interrogationHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu, uint8_t qoi);
    //控制命令响应
    static bool asduHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu);
    //中断响应
    friend void sigusr_handler(int signalId);

    void remote_cmd_handler(CS101_ASDU& asdu);
    //----------------------------------------------------------------------------------------------------------------
    //反向104连接事件处理
    static void reverse_connEventHandler(void* parameter, CS104_Connection connection, CS104_ConnectionEvent event);
    //反向104控制命令响应
    static bool reverse_recvAsduHandler(void* parameter, int address, CS101_ASDU asdu);
    //所有消息回调
    static void rawMessageHandler(void* parameter, uint8_t* msg, int msgSize, bool sent);

    static void  *handle_interrogation_proc(void *arg);
    static void  *handle_remotecmd_proc(void *arg);
    static void  *handle_remotepulse_proc(void *arg);
    static void  *handle_reconnect_proc(void *arg);


    CIec104ServiceManager        c_iec104ServiceManager;
protected:
    
    std::shared_ptr<CConfigManager>     c_cm;
    std::shared_ptr<DataCenterManager>  c_dcm;
    std::shared_ptr<CMosquittoManager>  c_mm;
    std::shared_ptr<TaskManager>        c_tm;

private:
    static void *comm_thread(void *arg);
    static void *monitor_thread(void *arg);
    static void *servermode_comm_thread(void *arg);

private:
    static  CIec104CommHandler          c_iec104CommHandler;
    
    CS104_Slave                         c_slave;
    CS101_AppLayerParameters            c_alParams;


    bool            c_connActived;
    char            c_register_code[64];
    std::string     c_master_addr;
    int             c_master_port;
    
    uint64_t        c_lastrecv_time;
    uint64_t        c_curr_time;
    pthread_t       c_thread_id_conn;
    pthread_t       c_thread_id_monitor;
    pthread_t       c_thrdid_servermode_conn;

    void append_measureinfobj_toasdu(int ti,CS101_ASDU Asdu, int ioa, float fval, CP56Time2a acq_time);
    void append_intertotalobj_toasdu(int ti, CS101_ASDU Asdu, ST_IEC104_INTERTOTAL_VAL stInterval);

};

#endif